Agent skills install from the npm packages the project already has - #219
Conversation
|
Important Review skippedToo many files! This PR contains 122 files, which is 22 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (122)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
8842b4c to
4350bb3
Compare
575a441 to
8e1b0a6
Compare
Adds `prisma skills sync` and `prisma skills list`, and the staleness
check every other command runs.
Skills now travel inside the Prisma packages a project installs, so a
copy in a harness skill directory is current only when its
`library_version` stamp matches the version of the package it came
from. Sync resolves the allowlisted packages by name from the project
root and from each declared workspace member, copies each skill tree
into the four harness directories, and removes copies whose source
package is gone. It never scans node_modules — the allowlist states why
that is permanent.
The check lives in main.ts after dispatch: every mounted family runs
through that one call, so the ORM and Composer families need no copy of
it. It writes one stderr line, never changes the exit code, and is
silenced by --quiet, --json/--format json, PRISMA_SKILLS_CHECK=0, CI,
`skills: { check: false }` in prisma.config.ts, and
`skills sync --disable`.
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Fixture projects in the layouts npm and pnpm produce, a workspace with two members pinning different versions, and a Yarn PnP fixture that patches Node's resolver and the filesystem module the way .pnp.cjs does — so the tests fail if the sync ever builds a node_modules path itself or reads through an API the PnP layer does not patch. Covers every state a copy can be in (in sync, stale, never synced, orphaned), pruning on package removal, leaving skills from other packages alone, exit 0 whenever there is nothing to do, and each of the check's off switches. The fixtures clear NODE_PATH first: vitest points it at this repository's pnpm store, which would otherwise make every fixture project look like it had two allowlisted packages installed. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
The staleness notice is not TTY-gated, which the update-notification section would otherwise imply is the rule for advisory stderr lines, so its own section says why and lists every way to silence it. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
`prisma --config <path> skills list` invokes the command that fixes stale skills, so the check must recognise the group even when shared flags come first. Also trims sync's help to the two examples the style guide asks for. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
A `packages/**` workspace made member enumeration walk the whole working tree — dist, coverage, .git, every source directory — and the resolver was then pointed at each one, four package names at a time. The staleness check runs that on every command, so an ordinary workspace pattern cost roughly a second per invocation instead of the milliseconds the design budgets. The walk now stops at a directory holding a package.json, because that directory is the member and everything below it is the package's own contents, and it never enters a dot-directory. Only directories with a package.json are returned, so `**` answers with packages rather than with directories. The new test counts directory reads rather than timing them: on a workspace with two built members it reads `packages` and `packages/group` and nothing else. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
`skills sync` printed `check: enabled` in a project whose
prisma.config.ts sets `skills: { check: false }`, contradicting
`skills list` and the check itself. It now needs the same config
section and combines it with the persisted opt-out the same way.
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The Agent Skills spec defines no custom top-level frontmatter keys; extensions live under `metadata`, a map of strings. Slices 1 and 4 are stamping `metadata.library` and `metadata.library_version`, so the reader follows them there and nowhere else. No fallback to the old top-level spelling: nothing has shipped one, and accepting both would let a skill claim a stamp the spec has no place for. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Operator decision: the published binary is `prisma`, so CLI_NAME — the one place the user-facing name lives — now says `prisma`, and every command string, notice, error next step, help line and sample output follows it. `prisma-cli` survives only where it names something that really is still called that: the `@prisma/cli` package's own bin (its README and the update check's entrypoint detection), the update-check cache directory, the repository URL, the sign-in campaign tag, and the legacy error copy the service group rewrites. That rewriting is why one behavioural change came with the rename: `fromLegacyCliError` turned a legacy `nextSteps` line into a run-command action only when it began `prisma-cli `, and dropped every other line. Legacy builders written with the new spelling would have lost their next steps, so the mapper now recognises both spellings and renames `<name> app ` to `<name> service ` either way. The feedback client's user-agent follows CLI_NAME too, so it now reports `prisma/<version>`; it identifies this binary, and this binary is called prisma. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
`/docs/orm/tools/prisma-cli` is the path that 308-redirects to the ORM CLI reference, which is the whole reason the comment cites it. The sweep matched it because the path was followed by a space, and output-conventions.md kept the right spelling, so the two disagreed. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
The mapper's current-spelling branch does have a producer — `computeConfigErrorToCliError` writes `prisma service <command>` into nextSteps, and `resolveComputeManagementContext` maps it — so removing the branch fails two tests in service-compute-config. What it lacked was a test that says so directly: those two fail for reasons that read as compute-config behaviour. These drive `renameAppCopy` and `fromLegacyCliError` with one spelling each, and pin the asymmetry that makes this worth covering — a command line the mapper does not recognise is dropped from nextActions rather than passed through, so an unrecognised spelling costs the user their next step with nothing to show for it. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Round-4 review fixes (S2-R3-1, S2-R3-2), committed at session halt; suites not re-run. Includes drive project artifacts up to this point. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
The branch's only cli-engine change was two doc-comment lines renamed in a prisma-cli -> prisma sweep. That trips the engine-version check because 0.2.0 is already published, and publishing the engine for comments is not worth it. Restore the file to origin/main byte-for-byte. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Both failures were in test fixtures, not production code — the skills library joins every path with path.join, which is correct on Windows. skills-pnp: the fake PnP layer remapped virtual paths with a startsWith check against a forward-slash prefix, but on Windows path.join hands it backslash paths, so the remap missed and sync found no packages. The fixture now compares in forward-slash form. skills-workspace-scan: the recorded readdir paths carry native separators, so the expected relative paths did not match on Windows. The assertion now normalizes separators before comparing; the set of directories it pins is unchanged. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…eout flake Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
User prisma.config.ts files import definePrismaConfig from prisma/config; the entry re-exports it from @prisma/cli-engine, which stays external, and ships its own types. @manypkg/tools comes in for the workspace enumeration rework. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
skills.agents in prisma.config.ts names which agent harnesses get skill copies; the default is every known agent (claude, cursor, agents, devin — windsurf is gone, its product renamed to Devin Desktop which reads .devin/skills). findProjectRoot is deleted: sync, list, the staleness notice, the post-login tip and the opt-out file all read from the directory the command runs in. The notice stays cheap: it reads the full agent set first and evaluates the config at most once, only when that already looks stale and only when a config file exists. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
The hand-written pnpm-workspace.yaml line parser and glob matcher go. PnpmTool and YarnTool read the declared globs from plain files (pnpm-workspace.yaml, package.json workspaces in both forms) and expand them with node_modules excluded, which covers npm, pnpm, bun and Yarn PnP alike and keeps the trust boundary: membership comes only from what the user declared, never from scanning installed packages. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
A fresh project gets a config with skills.agents spelled out; an existing prisma.config.ts is never edited — init reports the exact snippet to add instead. --skills takes the comma-separated agent list that both the scaffold and this run's sync use, or 'none' to skip the skills steps; --no-skills is gone. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
The temp project gets a node_modules/prisma symlink to the built package, so the scaffold's prisma/config import resolves exactly as in a user install, and the file init wrote is evaluated by the same loadConfig every command uses, asserting zero diagnostics. The rerun test removes the config first: the built binary cannot currently evaluate any prisma.config.ts in this repository's development layout (a defect that predates this work, reproduced at commit 7532706 with a dependency-free config; the c12 import inside the engine resolves through the pnpm symlink and misses its store siblings). The config-exists rerun stays covered in the unit suite. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
output-conventions and command-principles describe the agents map, the default set, init's scaffold and the never-edit rule; the prisma package declares @manypkg/tools so its bundle keeps the dependency external like its other runtime deps. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…file text Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…figs Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…project's config Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…requires packages/prisma pinned @prisma/orm-toolchain 8.0.0-rc.4 and @prisma/composer-cli 0.11.0 while bundling @prisma/cli source that requires rc.5 / 0.12.0. A command definition imported from rc.4 comes back undefined and the engine crashes with 'Cannot read properties of undefined (reading needs)' on every invocation, --version included. The skew is pre-existing on main. Align the pins with packages/cli. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
When the c12 specifier resolves through a pnpm symlink that is never realpath'd (the dev workspace layout, and pnpm installs with hoist=false), c12's own 'import "pathe"' walks up from the symlink path, where its store siblings are unreachable, and every config evaluation fails with CLI.CONFIG_UNREADABLE: Cannot find package 'pathe'. Import c12 through the realpath of its resolved URL instead. A resolution failure still throws inside evaluateConfigFile, so it still surfaces as the unreadable-config diagnostic. The import-purity conformance check now excuses c12 from the reverse (unimported-dependency) half: import.meta.resolve is not an import, which is the exact case allowedUnimported exists for. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
The rerun no longer deletes prisma.config.ts before invoking the built binary: with c12 imported through its realpath the binary can evaluate the config in this repository's layout, so the test now asserts the honest behavior — a second init with the config present reports the config step as exists and exits 0. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
An engine change forces a version bump, and the published families peer-pin the engine exactly, so shipping it means a coordinated family release. The defect only affects this repo's dev layout and pnpm hoist=false installs — npm and default pnpm installs evaluate configs fine — so it waits for the next engine train. The verified one-line fix (import c12 through its realpath) is recorded in the e2e comment and the ledger. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
857bed4 to
85beca3
Compare
…oes quiet Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…30096) The prisma-8 skill now ships inside the npm tarballs users actually install, instead of being fetched from GitHub by `npx skills add` at init time. ## What changed - **The two upgrade skills fold into the `prisma-8` router.** `prisma-next-upgrade` and `prisma-8-extension-upgrade` become an "upgrading" branch of `skills/prisma-8/` (per-transition `upgrades/<from>-to-<to>/` layout kept), their trigger phrases move into the router's `description`, and the router opens with a preamble telling the agent the installed version's skill is the source of truth. Three registered skills become one. - **Version stamp under `metadata`.** The skill frontmatter carries `metadata.library` (the npm package name) and `metadata.library_version`, stamped by the version pipeline (`scripts/set-version.ts`) so the stamp and the package version cannot diverge. The keys live under the Agent Skills spec's `metadata` map — a string→string extension point — rather than as undefined top-level keys. - **The skill travels in three tarballs.** `skills/prisma-8/` is staged into `@prisma/orm-postgres`, `@prisma/orm-sqlite`, and `@prisma/orm-mongo` at `prepack` time, with `"skills"` in each package's `files`. Each copy's `metadata.library` names the package it ships in. - **The packaging is proved from the artifact, not the working tree.** The publish-surface test deletes the staged tree, runs `pnpm pack` the way the publish workflow does, reads the stamped `SKILL.md` back out of the tarball, and byte-compares every file against the tracked source. It fails if the `files` entry or the `prepack` script is removed. - **The upgrade-coverage check follows the fold.** `USER_SKILL_PKG` / `EXT_SKILL_PKG` point at the folded directories and the path regex is derived from them. - Docs updated: `skills/README.md` (authoring rules for the stamp, the GitHub route demoted to a manual fallback), `docs/oss/versioning.md`, `docs/reference/error-reference.md`. ## What consumes this `prisma skills sync` in prisma/prisma-cli ([prisma/prisma-cli#219](prisma/prisma-cli#219)) copies these skills from the installed packages into the agent harness directories and reads the `metadata` stamp to detect staleness. The init wiring that runs sync lands separately, stacked on this branch. Merge order: prisma/prisma-cli#219 ships first (it owns the `prisma skills` command), then this, then the init wiring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Prisma ORM packages now bundle a version-matched `prisma-8` skill for application and extension upgrades. * Added upgrade guidance and migration tools covering historical Prisma version transitions. * Skills now synchronize automatically during package initialization and packaging. * **Documentation** * Updated installation, synchronization, versioning, error-handling, and authoring guidance. * **Bug Fixes** * Improved skill metadata validation and version stamping. * Retired legacy standalone upgrade skill references and installation paths. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…kills setup (prisma#30097) `prisma orm init` stops delivering agent skills entirely. The old GitHub fetch (`npx skills add`) is removed, and init does not run `prisma skills sync` either: skills setup belongs to the family-level `prisma init` command that ships in [prisma/prisma-cli#219](prisma/prisma-cli#219). > Operator ruling (Will Madden, 2026-08-21): `prisma orm init` must not run `skills sync` at scaffold time — the family-level `prisma init` owns skills setup. An earlier revision of this branch ran the sync once at scaffold time with a `--skip-skills` opt-out; both are removed. Stacked on prisma#30096 (the tarball packaging). Retarget to `main` after prisma#30096 merges. ## What changed - **Init runs no skills command at all.** `DEFAULT_SKILL_SOURCES`' GitHub invocations are gone and nothing replaced them: no `skills add`, no `skills sync`, no postinstall script, no skill gitignore entries. The `--skip-skills` flag is removed with the behavior it opted out of. Init's next-steps list carries one pointer: run `prisma init` in the project to set up the agent skills. The integration test asserts init spawns no skills command and fetches nothing from GitHub. - **One binary everywhere.** The CLI dev dependency is `prisma@next` — the package that actually carries the `prisma` bin — and every string init writes or runs uses it: the engine-version probe, the emit spawn, the `contract:emit` script, next-actions, and the scaffold quick-reference. The integration test asserts one binary end to end. - **The skill-install failure path is retired.** Exit code 6 and `skillInstallFailedFinding` are removed; `error-reference.md` updated. - **Retired skill directories are still cleaned up.** Init keeps deleting the pre-`prisma-8` skill directories it finds in the agent harness roots. ## Notes for reviewers - Existing projects are untouched: they keep `@prisma/cli` and `prisma-cli` scripts, which still work. Whether to ship a migration entry for them is a product decision left open deliberately. - The repo-wide `prisma-cli` → `prisma` string rename (~10 `fix:` strings, root README) is deliberately not part of this change and needs its own owner. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - `prisma orm init` now focuses on project setup and no longer installs or synchronizes agent skills. - Run `prisma init` to configure skills, or `prisma skills sync` to refresh them. - Contract emission now uses the project’s local `prisma` command. - **Documentation** - Updated setup guidance, examples, error references, and quick references to use the current `prisma orm init` and `prisma` command syntax. - Removed obsolete skill-installation options and instructions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
In a project that has
@prisma/orm-postgresinstalled, this now works — no network, no extra tooling:And after
pnpm up @prisma/orm-postgresbumps the package but nobody re-runs sync, everyprismacommand appends one line to stderr:The decision
Agent skills now travel inside the npm packages they describe, and this PR adds the CLI half of that:
prisma skills synccopies them into place,prisma skills listreports status,prisma initsets a project up once, and a staleness notice after every command keeps the copies from silently rotting.An agent skill is a directory with a
SKILL.md— instructions that teach a coding agent (Claude Code, Cursor, Codex, Windsurf) how to use a library. Each harness auto-indexes skills from a known project directory (.claude/skills/,.cursor/skills/,.agents/skills/,.windsurf/skills/); a skill anywhere else is invisible. So a skill is only useful if something copies it into those directories and keeps the copy matching the installed package version. Until now that something wasprisma orm initshelling out to a third-party CLI that cloned our skills from GitHub at a ref named after the package version — a convention, not a guarantee — and nothing ever detected that the copies had gone stale.How sync decides what to install
Sync resolves a hardcoded allowlist of four packages —
@prisma/orm-postgres,@prisma/orm-sqlite,@prisma/orm-mongo,@prisma/composer— by name from the project root and each workspace member directory. It never scansnode_modules: a skill is instructions an agent will follow, so a scanner would let any transitive dependency inject instructions into the agent. That invariant is stated (and marked permanent) at the allowlist declaration, and this PR's trust boundary is exactly the code's — the only skills installed come from packages the user deliberately installed.Each shipped
SKILL.mdcarries a version stamp in its frontmatter, under the Agent Skills spec'smetadatamap (custom top-level keys are not spec-defined):Sync compares the installed package's version against the stamp in each harness copy and re-copies on mismatch. Pruning removes only copies whose stamp names an allowlisted package that is no longer installed — a skill some other tool put there is never touched. The synced copies are ordinary files git tracks; sync removes the
*ignore file an earlier revision wrote into its copies, but leaves any.gitignorea user authored in place. If two workspace members pin different versions of one package, the highest wins and sync warns. Yarn PnP works because all reads go through Node's resolution and fs layers (there is a test that fakes the PnP zip filesystem to prove it).Sync refuses what it does not own. A target directory whose
SKILL.mdis unstamped, unreadable, or stamped by a non-allowlisted package — a hand-written skill colliding on name — is left byte-for-byte intact, reported in arefusedarray and aSKILLS.UNMANAGED_DIRECTORYdiagnostic, and the summary line never claims "up to date" without naming it. A directory whoseSKILL.mdis genuinely absent (an interrupted copy) is repaired.prisma initprisma initinitializes a repository for Prisma development, purely locally — no platform calls. Two steps, each with an opt-out (--no-postinstall,--no-skills), always exit 0, never prompts, idempotent:"postinstall": "prisma skills sync || exit 0"to the current directory'spackage.json, so skills resync on every install and upgrade. A different existing postinstall script is never clobbered or chained — init reports it and tells the user what to append. BOM, CRLF, indentation, and trailing-newline style are preserved; an unreadable, unwritable, or malformed manifest is a diagnostic, not a failure.This is a new command reusing a retired name: #218 deleted the old compute-config wizard, and nothing from it returns. Sync itself still never touches
package.json(a test pins byte-identity across a sync run) — writing the hook is exclusively the act of a user runninginit.The
prisma agentgroup is deletedprisma agent install|update|status— the old installer that shelled out tonpx skills@latestfor the v6/v7 skills — is gone (operator ruling, 2026-08-21). The post-login tip that advertised it now offersprisma skills syncinstead, only when installed packages actually have stale copies, and can no longer fail a login that already succeeded.The staleness notice
It prints to stderr, after the command's own output, never changes the exit code, and is deliberately not TTY-dependent — its main reader is an agent running the CLI without one. Off switches:
--quiet,--json/--format json,--version,PRISMA_SKILLS_CHECK=0,CI/GITHUB_ACTIONS,skills: { check: false }inprisma.config.ts(an explicit--config <path>is honored), a persistent opt-out written byprisma skills sync --disable(stored in.prisma/skills.json), and anyskillscommand itself. Flag scanning stops at a bare--. The per-command cost is stat calls and small file reads;prisma.config.tsis only evaluated after staleness is already established. With the init-written postinstall as the primary trigger, the notice is the backstop for projects that never raninitor removed the script.Pin and state dir find the project root
.prisma/local.json(the link pin) and the state dir are now discovered by walking up from the cwd to the nearest directory containing.prisma/— a pure filesystem check, no config file is read — so a repo linked at its root works fromapps/api/. Nearest wins deliberately: a subdirectory linked to a different project beats the root. Commands that rewrite or delete the pin operate on the file they found, not on the cwd. When no.prisma/exists, behavior is unchanged.The rename:
CLI_NAMEis nowprismaThe published package (
prisma) has installed a bin namedprismasince 8.0.0-rc.3, but every string the CLI printed still saidprisma-cli. This PR movesCLI_NAME, so help text, error guidance, and the notice above all name the binary users actually have. There is no compatibility layer: the CLI is pre-rc and owes old spellings nothing, so every producer of error guidance was fixed to emit the current commands directly, and the display-time rewriter that used to patch up legacy spellings (renameAppCopyand friends) was deleted rather than extended.fromLegacyCliErrorsurvives only as a structural converter (legacy error shape →CliError); it no longer rewrites or filters any copy. Deliberate survivals, so nobody "finishes" the rename by mistake: the@prisma/clipackage's own bin and README, the update-check entrypoint matcher and cache directory,git@github.com:prisma/prisma-cli.gitrepo URLs, and theutm_source/utm_campaignsign-in tags.Tests
90+ new tests: npm/pnpm/Yarn-PnP fixture projects, every sync/check state (stale, never-synced, in-sync, refused, opted out), the collision and unreadable-skill refusals (chmod-based), pruning on package removal, a two-member monorepo with the version-conflict warning, every off switch, init's full package.json edge-case matrix (foreign script, non-object
scripts, BOM, CRLF, read-only file, missing manifest), a credential-free e2e driving the built binary throughinittwice, areaddir-count regression test bounding workspace-glob expansion, and the legacy-error mapper suite.For other owners
prisma-cli/<version>toprisma/<version>— wire-visible; whoever reads that dashboard should know.isLikelyGlobalNpmEntrypoint(update-check) still matches onlyprisma-cliinstall paths, so a globally installedprismagets the docs-link fallback instead of a concrete update command. Pre-existing, untouched here, newly conspicuous.npx skills add prisma/skillscopy button — the last surface promoting the retired installer; its removal is pending an operator decision.orm init) drops its scaffold-time sync call per operator ruling — follow-up on that PR.Merge order: #218 is merged; this PR next, then prisma/prisma#30096 (packaging) → #30097, and prisma/composer#251's npm release — all ship skills only this CLI can read.
Alternatives considered
npx skills add(status quo): version matched by ref-name convention only, unmanaged copies, network access during init, and an unpinned third-party CLI in our init path.node_modules: prompt-injection by construction — any transitive dependency could plant instructions. Permanently rejected.node_modulesinstead of copies: nonode_modulesunder Yarn PnP, symlink creation needs elevation on Windows, and only Claude Code documents following symlinked skills. Version-stamped, checked, auto-resynced copies are a managed cache.AGENTS.mdtelling agents to run sync each session: rejected by the team — agents shouldn't carry maintenance duties.postinstallin our own packages: dependency lifecycle scripts are blocked by default in pnpm 10+, bun, and Deno. Permanently rejected.postinstallfromprisma orm initor from sync itself (the original design): rejected — a routine command silently editing yourpackage.json, or re-adding a script you removed, is not acceptable. The operator's final ruling: the hook is written only byprisma init, a command whose whole point the user invokes deliberately; nothing automatic ever edits the manifest, and the staleness notice covers everyone else.🤖 Generated with Claude Code